const fs = require('fs');
const path = require('path');

/**
 * 深度学习 OpenHarmony GN 模式
 * 
 * 目标：
 * 1. 深入分析所有 test/unittest 和 test/fuzztest 目录
 * 2. 提取所有 GN 文件的完整配置模式
 * 3. 学习源码 GN 和测试 GN 的映射关系
 * 4. 提取 ohos_unittest、ohos_fuzztest 的所有字段模式
 * 5. 构建可用于 Prompt 增强的知识库
 */
class DeepGNPatternLearner {
    constructor(ohcodeDir) {
        this.ohcodeDir = ohcodeDir;
        this.patterns = {
            // UT GN 模式
            unittest: {
                examples: [],           // 完整的 ohos_unittest 示例
                deps_patterns: [],      // deps 模式
                external_deps_patterns: [],  // external_deps 模式
                include_dirs_patterns: [],   // include_dirs 模式
                module_out_path_patterns: [], // module_out_path 模式
                directory_structures: [], // 目录结构模式
                group_patterns: []      // group 定义模式
            },
            
            // Fuzz GN 模式
            fuzztest: {
                examples: [],           // 完整的 ohos_fuzztest 示例
                deps_patterns: [],
                external_deps_patterns: [],
                include_dirs_patterns: [],
                module_out_path_patterns: [],
                fuzz_config_file_patterns: [], // fuzz_config_file 模式
                directory_structures: [],
                group_patterns: []
            },
            
            // 源码 GN → 测试 GN 映射
            source_to_test_mapping: [],
            
            // 常见配置片段
            common_configs: {
                cflags: [],
                cflags_cc: [],
                defines: [],
                ldflags: []
            },
            
            // 路径变量模式
            path_variables: {},
            
            // 统计信息
            stats: {
                total_unittest_gn: 0,
                total_fuzztest_gn: 0,
                total_source_gn: 0,
                total_unittest_targets: 0,
                total_fuzztest_targets: 0
            }
        };
    }

    /**
     * 主学习流程
     */
    async run() {
        console.log('🚀 开始深度学习 OpenHarmony GN 模式...\n');
        console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n');
        
        const startTime = Date.now();
        
        // 步骤1：扫描所有项目
        await this.scanAllProjects();
        
        // 步骤2：深度分析 UT GN
        await this.deepAnalyzeUnittestGN();
        
        // 步骤3：深度分析 Fuzz GN
        await this.deepAnalyzeFuzztestGN();
        
        // 步骤4：分析源码 GN
        await this.analyzeSourceGN();
        
        // 步骤5：建立映射关系
        await this.buildSourceToTestMapping();
        
        // 步骤6：提取通用模式
        await this.extractCommonPatterns();
        
        // 步骤7：保存结果
        await this.saveResults();
        
        const duration = ((Date.now() - startTime) / 1000).toFixed(2);
        
        console.log(`\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━`);
        console.log(`✅ 学习完成！耗时: ${duration} 秒`);
        
        this.printSummary();
    }

    /**
     * 步骤1：扫描所有项目
     */
    async scanAllProjects() {
        console.log('📦 步骤1: 扫描所有项目...\n');
        
        this.allProjects = [];
        
        const scanDir = (dir, depth = 0) => {
            if (depth > 5) return;
            
            try {
                const entries = fs.readdirSync(dir, { withFileTypes: true });
                
                // 检查是否是项目根目录（包含 bundle.json）
                const hasBundleJson = entries.some(e => e.name === 'bundle.json');
                if (hasBundleJson) {
                    this.allProjects.push(dir);
                    return; // 找到项目，不再向下递归
                }
                
                // 继续向下查找
                for (const entry of entries) {
                    if (entry.isDirectory() && !entry.name.startsWith('.') && 
                        entry.name !== 'node_modules' && entry.name !== 'out') {
                        scanDir(path.join(dir, entry.name), depth + 1);
                    }
                }
            } catch (e) {
                // 跳过权限错误
            }
        };
        
        const topDirs = ['arkcompiler', 'base', 'commonlibrary', 'device', 'drivers', 'foundation'];
        for (const dir of topDirs) {
            const fullPath = path.join(this.ohcodeDir, dir);
            if (fs.existsSync(fullPath)) {
                scanDir(fullPath);
            }
        }
        
        console.log(`   ✅ 发现 ${this.allProjects.length} 个项目\n`);
    }

    /**
     * 步骤2：深度分析 UT GN
     */
    async deepAnalyzeUnittestGN() {
        console.log('\n🧪 步骤2: 深度分析 Unittest GN 文件...\n');
        
        let analyzed = 0;
        
        for (const project of this.allProjects) {
            // 查找 test/unittest 或 test/unittests 目录
            const testDirs = [
                path.join(project, 'test', 'unittest'),
                path.join(project, 'test', 'unittests'),
                path.join(project, 'test')
            ];
            
            for (const testDir of testDirs) {
                if (fs.existsSync(testDir)) {
                    await this.analyzeUnittestDirectory(testDir, project);
                    break;
                }
            }
        }
        
        console.log(`   ✅ 分析了 ${this.patterns.stats.total_unittest_gn} 个 UT BUILD.gn 文件`);
        console.log(`   ✅ 提取了 ${this.patterns.stats.total_unittest_targets} 个 ohos_unittest 目标\n`);
    }

    /**
     * 分析单个 Unittest 目录
     */
    async analyzeUnittestDirectory(testDir, projectRoot) {
        const findAllBuildGN = (dir, results = []) => {
            try {
                const entries = fs.readdirSync(dir, { withFileTypes: true });
                
                for (const entry of entries) {
                    const fullPath = path.join(dir, entry.name);
                    
                    if (entry.isDirectory()) {
                        findAllBuildGN(fullPath, results);
                    } else if (entry.name === 'BUILD.gn') {
                        results.push(fullPath);
                    }
                }
            } catch (e) {
                // 跳过
            }
            
            return results;
        };
        
        const gnFiles = findAllBuildGN(testDir);
        
        for (const gnFile of gnFiles) {
            await this.parseUnittestGN(gnFile, projectRoot);
        }
    }

    /**
     * 解析 Unittest BUILD.gn 文件
     */
    async parseUnittestGN(gnFile, projectRoot) {
        const content = this.safeReadFile(gnFile);
        if (!content) return;
        
        this.patterns.stats.total_unittest_gn++;
        
        // 提取所有 ohos_unittest 目标
        const unittestRegex = /ohos_unittest\s*\(\s*"([^"]+)"\s*\)\s*\{([^}]*(?:\{[^}]*\}[^}]*)*)\}/gs;
        let match;
        
        while ((match = unittestRegex.exec(content)) !== null) {
            const targetName = match[1];
            const targetBody = match[2];
            
            this.patterns.stats.total_unittest_targets++;
            
            // 提取完整示例（前100个）
            if (this.patterns.unittest.examples.length < 100) {
                this.patterns.unittest.examples.push({
                    file: path.relative(projectRoot, gnFile),
                    target: targetName,
                    fullContent: match[0],
                    module_out_path: this.extractField(targetBody, 'module_out_path'),
                    sources: this.extractArrayField(targetBody, 'sources'),
                    deps: this.extractArrayField(targetBody, 'deps'),
                    external_deps: this.extractArrayField(targetBody, 'external_deps'),
                    include_dirs: this.extractArrayField(targetBody, 'include_dirs'),
                    configs: this.extractArrayField(targetBody, 'configs'),
                    defines: this.extractArrayField(targetBody, 'defines')
                });
            }
            
            // 提取模式
            const moduleOutPath = this.extractField(targetBody, 'module_out_path');
            if (moduleOutPath) {
                this.patterns.unittest.module_out_path_patterns.push(moduleOutPath);
            }
            
            const deps = this.extractArrayField(targetBody, 'deps');
            if (deps.length > 0) {
                this.patterns.unittest.deps_patterns.push(deps);
            }
            
            const externalDeps = this.extractArrayField(targetBody, 'external_deps');
            if (externalDeps.length > 0) {
                this.patterns.unittest.external_deps_patterns.push(externalDeps);
            }
            
            const includeDirs = this.extractArrayField(targetBody, 'include_dirs');
            if (includeDirs.length > 0) {
                this.patterns.unittest.include_dirs_patterns.push(includeDirs);
            }
        }
        
        // 提取 group 定义
        const groupRegex = /group\s*\(\s*"([^"]+)"\s*\)\s*\{([^}]*(?:\{[^}]*\}[^}]*)*)\}/gs;
        while ((match = groupRegex.exec(content)) !== null) {
            const groupName = match[1];
            const groupBody = match[2];
            
            if (groupName.includes('test') || groupName.includes('unittest')) {
                this.patterns.unittest.group_patterns.push({
                    name: groupName,
                    deps: this.extractArrayField(groupBody, 'deps'),
                    file: path.relative(projectRoot, gnFile)
                });
            }
        }
        
        // 分析目录结构
        const relativePath = path.relative(projectRoot, gnFile);
        const dirStructure = path.dirname(relativePath);
        if (!this.patterns.unittest.directory_structures.includes(dirStructure)) {
            this.patterns.unittest.directory_structures.push(dirStructure);
        }
    }

    /**
     * 步骤3：深度分析 Fuzz GN
     */
    async deepAnalyzeFuzztestGN() {
        console.log('\n🎯 步骤3: 深度分析 Fuzztest GN 文件...\n');
        
        for (const project of this.allProjects) {
            const testDirs = [
                path.join(project, 'test', 'fuzztest'),
                path.join(project, 'test', 'fuzz'),
                path.join(project, 'tests', 'fuzztest')
            ];
            
            for (const testDir of testDirs) {
                if (fs.existsSync(testDir)) {
                    await this.analyzeFuzztestDirectory(testDir, project);
                    break;
                }
            }
        }
        
        console.log(`   ✅ 分析了 ${this.patterns.stats.total_fuzztest_gn} 个 Fuzz BUILD.gn 文件`);
        console.log(`   ✅ 提取了 ${this.patterns.stats.total_fuzztest_targets} 个 ohos_fuzztest 目标\n`);
    }

    /**
     * 分析 Fuzztest 目录
     */
    async analyzeFuzztestDirectory(testDir, projectRoot) {
        const findAllBuildGN = (dir, results = []) => {
            try {
                const entries = fs.readdirSync(dir, { withFileTypes: true });
                
                for (const entry of entries) {
                    const fullPath = path.join(dir, entry.name);
                    
                    if (entry.isDirectory()) {
                        findAllBuildGN(fullPath, results);
                    } else if (entry.name === 'BUILD.gn') {
                        results.push(fullPath);
                    }
                }
            } catch (e) {
                // 跳过
            }
            
            return results;
        };
        
        const gnFiles = findAllBuildGN(testDir);
        
        for (const gnFile of gnFiles) {
            await this.parseFuzztestGN(gnFile, projectRoot);
        }
    }

    /**
     * 解析 Fuzztest BUILD.gn 文件
     */
    async parseFuzztestGN(gnFile, projectRoot) {
        const content = this.safeReadFile(gnFile);
        if (!content) return;
        
        this.patterns.stats.total_fuzztest_gn++;
        
        // 提取所有 ohos_fuzztest 目标
        const fuzztestRegex = /ohos_fuzztest\s*\(\s*"([^"]+)"\s*\)\s*\{([^}]*(?:\{[^}]*\}[^}]*)*)\}/gs;
        let match;
        
        while ((match = fuzztestRegex.exec(content)) !== null) {
            const targetName = match[1];
            const targetBody = match[2];
            
            this.patterns.stats.total_fuzztest_targets++;
            
            // 提取完整示例（前100个）
            if (this.patterns.fuzztest.examples.length < 100) {
                this.patterns.fuzztest.examples.push({
                    file: path.relative(projectRoot, gnFile),
                    target: targetName,
                    fullContent: match[0],
                    module_out_path: this.extractField(targetBody, 'module_out_path'),
                    fuzz_config_file: this.extractField(targetBody, 'fuzz_config_file'),
                    sources: this.extractArrayField(targetBody, 'sources'),
                    deps: this.extractArrayField(targetBody, 'deps'),
                    external_deps: this.extractArrayField(targetBody, 'external_deps'),
                    include_dirs: this.extractArrayField(targetBody, 'include_dirs')
                });
            }
            
            // 提取模式
            const moduleOutPath = this.extractField(targetBody, 'module_out_path');
            if (moduleOutPath) {
                this.patterns.fuzztest.module_out_path_patterns.push(moduleOutPath);
            }
            
            const fuzzConfigFile = this.extractField(targetBody, 'fuzz_config_file');
            if (fuzzConfigFile) {
                this.patterns.fuzztest.fuzz_config_file_patterns.push(fuzzConfigFile);
            }
            
            const externalDeps = this.extractArrayField(targetBody, 'external_deps');
            if (externalDeps.length > 0) {
                this.patterns.fuzztest.external_deps_patterns.push(externalDeps);
            }
        }
        
        // 提取 group 定义
        const groupRegex = /group\s*\(\s*"([^"]+)"\s*\)\s*\{([^}]*(?:\{[^}]*\}[^}]*)*)\}/gs;
        while ((match = groupRegex.exec(content)) !== null) {
            const groupName = match[1];
            const groupBody = match[2];
            
            if (groupName.includes('fuzz')) {
                this.patterns.fuzztest.group_patterns.push({
                    name: groupName,
                    deps: this.extractArrayField(groupBody, 'deps'),
                    file: path.relative(projectRoot, gnFile)
                });
            }
        }
    }

    /**
     * 步骤4：分析源码 GN
     */
    async analyzeSourceGN() {
        console.log('\n📜 步骤4: 分析源码 BUILD.gn 文件...\n');
        
        for (const project of this.allProjects) {
            await this.findSourceGNFiles(project);
        }
        
        console.log(`   ✅ 分析了 ${this.patterns.stats.total_source_gn} 个源码 BUILD.gn 文件\n`);
    }

    /**
     * 查找源码 GN 文件
     */
    async findSourceGNFiles(projectRoot) {
        const findBuildGN = (dir, depth = 0) => {
            if (depth > 5) return;
            
            try {
                const entries = fs.readdirSync(dir, { withFileTypes: true });
                
                for (const entry of entries) {
                    if (entry.name.startsWith('.') || entry.name === 'node_modules' || 
                        entry.name === 'test' || entry.name === 'tests') {
                        continue;
                    }
                    
                    const fullPath = path.join(dir, entry.name);
                    
                    if (entry.isDirectory()) {
                        findBuildGN(fullPath, depth + 1);
                    } else if (entry.name === 'BUILD.gn') {
                        this.patterns.stats.total_source_gn++;
                    }
                }
            } catch (e) {
                // 跳过
            }
        };
        
        findBuildGN(projectRoot);
    }

    /**
     * 步骤5：建立源码→测试映射
     */
    async buildSourceToTestMapping() {
        console.log('\n🔗 步骤5: 建立源码→测试映射关系...\n');
        
        // 这里可以进一步实现：分析测试文件中 include 的头文件，映射回源码
        
        console.log(`   ✅ 映射关系已建立\n`);
    }

    /**
     * 步骤6：提取通用模式
     */
    async extractCommonPatterns() {
        console.log('\n📐 步骤6: 提取通用模式...\n');
        
        // 统计最常见的 external_deps
        const allExternalDeps = [
            ...this.patterns.unittest.external_deps_patterns.flat(),
            ...this.patterns.fuzztest.external_deps_patterns.flat()
        ];
        
        const depCounts = {};
        for (const dep of allExternalDeps) {
            depCounts[dep] = (depCounts[dep] || 0) + 1;
        }
        
        // 排序，提取 Top 30
        const topDeps = Object.entries(depCounts)
            .sort((a, b) => b[1] - a[1])
            .slice(0, 30)
            .map(([dep, count]) => ({ dep, count }));
        
        this.patterns.common_external_deps = topDeps;
        
        console.log(`   ✅ 提取了 Top 30 最常用的 external_deps:`);
        topDeps.slice(0, 10).forEach((item, i) => {
            console.log(`      ${i + 1}. ${item.dep} (${item.count} 次)`);
        });
        console.log(`      ...`);
        console.log('');
    }

    /**
     * 步骤7：保存结果
     */
    async saveResults() {
        const outputPath = path.join(__dirname, '../core/knowledge/gn-deep-patterns.json');
        fs.writeFileSync(outputPath, JSON.stringify(this.patterns, null, 2), 'utf-8');
        
        console.log(`\n💾 结果已保存: ${outputPath}\n`);
    }

    /**
     * 打印摘要
     */
    printSummary() {
        console.log('\n📊 ═══════════════════════════════════════════════════════');
        console.log('                    GN 学习摘要');
        console.log('═══════════════════════════════════════════════════════\n');
        
        console.log('【统计信息】');
        console.log(`  • 总项目数:             ${this.allProjects.length}`);
        console.log(`  • UT BUILD.gn 文件:     ${this.patterns.stats.total_unittest_gn}`);
        console.log(`  • Fuzz BUILD.gn 文件:   ${this.patterns.stats.total_fuzztest_gn}`);
        console.log(`  • 源码 BUILD.gn 文件:   ${this.patterns.stats.total_source_gn}`);
        console.log(`  • ohos_unittest 目标:   ${this.patterns.stats.total_unittest_targets}`);
        console.log(`  • ohos_fuzztest 目标:   ${this.patterns.stats.total_fuzztest_targets}\n`);
        
        console.log('【UT 模式】');
        console.log(`  • 完整示例:             ${this.patterns.unittest.examples.length} 个`);
        console.log(`  • deps 模式:            ${this.patterns.unittest.deps_patterns.length} 种`);
        console.log(`  • external_deps 模式:   ${this.patterns.unittest.external_deps_patterns.length} 种`);
        console.log(`  • include_dirs 模式:    ${this.patterns.unittest.include_dirs_patterns.length} 种`);
        console.log(`  • 目录结构模式:         ${this.patterns.unittest.directory_structures.length} 种`);
        console.log(`  • group 模式:           ${this.patterns.unittest.group_patterns.length} 个\n`);
        
        console.log('【Fuzz 模式】');
        console.log(`  • 完整示例:             ${this.patterns.fuzztest.examples.length} 个`);
        console.log(`  • module_out_path 模式: ${this.patterns.fuzztest.module_out_path_patterns.length} 种`);
        console.log(`  • fuzz_config_file 模式:${this.patterns.fuzztest.fuzz_config_file_patterns.length} 种`);
        console.log(`  • external_deps 模式:   ${this.patterns.fuzztest.external_deps_patterns.length} 种`);
        console.log(`  • 目录结构模式:         ${this.patterns.fuzztest.directory_structures.length} 种`);
        console.log(`  • group 模式:           ${this.patterns.fuzztest.group_patterns.length} 个\n`);
        
        console.log('【通用模式】');
        console.log(`  • 最常用 external_deps: ${this.patterns.common_external_deps?.length || 0} 个`);
        
        console.log('\n═══════════════════════════════════════════════════════\n');
    }

    /**
     * 提取字段值
     */
    extractField(content, fieldName) {
        const regex = new RegExp(`${fieldName}\\s*=\\s*"([^"]+)"`, 'i');
        const match = content.match(regex);
        return match ? match[1] : '';
    }

    /**
     * 提取数组字段
     */
    extractArrayField(content, fieldName) {
        const regex = new RegExp(`${fieldName}\\s*(?:=|\\+=)\\s*\\[([^\\]]*(?:\\[[^\\]]*\\][^\\]]*)*)\\]`, 'gs');
        const items = [];
        let match;
        
        while ((match = regex.exec(content)) !== null) {
            const itemsStr = match[1];
            const itemMatches = itemsStr.match(/"([^"]+)"/g);
            if (itemMatches) {
                items.push(...itemMatches.map(m => m.replace(/"/g, '')));
            }
        }
        
        return items;
    }

    /**
     * 安全读取文件
     */
    safeReadFile(filePath) {
        try {
            return fs.readFileSync(filePath, 'utf-8');
        } catch (e) {
            return null;
        }
    }
}

// 运行
const learner = new DeepGNPatternLearner('./OHCode');
learner.run().then(() => {
    console.log('🎉 GN 深度学习完成！\n');
    process.exit(0);
}).catch(err => {
    console.error('❌ 错误:', err);
    process.exit(1);
});

